package wykop.parser;

import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;

import wykop.dataBase.UserManager;
import wykop.page.WykopComment;
import wykop.page.WykopPage;
import wykop.page.WykopUser;
import wykop.utils.Convert;
import wykop.utils.XPathUtils;

import com.google.common.base.Preconditions;
import com.google.common.collect.Sets;

/**
 * Created by IntelliJ IDEA. User: kad Date: 05.11.11 Time: 10:46 To change this
 * template use File | Settings | File Templates.
 */
public class WykopPageParser {

	private static final String TITLE_SELECTOR = "/html/body/div/div/section/div/article/div[@class='clr']/div[@class='content']/header/h2/a/span[@class='fbold']";
	private static final String USER_NAME_SELECTOR = "/html/body/div/div/aside/div/h4/a";
	private static final String SCORE_SELECTOR = "/html/body/div/div/section/div/article/div/div/a/span";
	private static final String COMMENTS_SELECTOR = "/html/body/div/div/section/div/ul[@id=\'comments-list-entry\']/li";

	private final ICommentParser commentParser;
	private final UserProvider userProvider;

	private final static Logger logger = Logger.getLogger("wykop.parser.page");

	public static WykopPageParser getDefault() {
		final UserProvider userProvider = UserManager.getUserProvider();
		return new WykopPageParser(
				WykopCommentParser.getCommentParser(userProvider), userProvider);
	}

	private static Set<WykopComment> parseComments(final Node node,
			final ICommentParser commentParser) {
		final Set<WykopComment> comments = Sets.newHashSet();
		final List<Node> nodes = XPathUtils.extractNodes(node,
				COMMENTS_SELECTOR);
		int number = 0;
		for (final Node commentNode : nodes) {
			number++;
			try {
				final WykopComment comment = commentParser
						.parseComment(commentNode);
				comment.setNumberOnPage(number);
				comments.add(comment);
			} catch (final NoCommentParsed noCommentParsed) {
				// Error should be reported by sender
			}
		}

		return comments;

	}

	public WykopPageParser(final ICommentParser commentParser,
			final UserProvider userProvider) {
		this.commentParser = commentParser;
		this.userProvider = userProvider;
	}

	public WykopPage parse(final int i, final Node node) throws PageNotParsed {
		Preconditions.checkNotNull(node);

		logger.info("Parsing page: " + i);
		try {
			final String title = XPathUtils.extractString(node, TITLE_SELECTOR);
			final String userName = XPathUtils.extractString(node,
					USER_NAME_SELECTOR);
			final WykopUser user = userProvider.getUserForName(userName);
			final int score = Convert.toInt(XPathUtils
					.extractString(node, SCORE_SELECTOR).replace("wykop", "")
					.trim());

			final WykopPage page = new WykopPage();
			page.setTitle(title);
			page.setAuthor(user);
			page.setScore(score);
			page.setComments(parseComments(node, commentParser));

			for (final WykopComment comment : page.getComments()) {
				comment.setPage(page);
			}

			logger.debug("Parsing page " + i + " completed");

			return page;
		} catch (final Exception e) {
			logger.warn("Failed to parse page: " + i, e);
			throw new PageNotParsed(e);
		}

	}

}
